﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Arbore;
using Operators;
using Satates;
using Common;

namespace Algorithms.HillClimbing
{
    public class HillClimbing:Algorithm
    {
        private bool switcher;
        private bool result = false;
        private iHeuristic h;
        Arbore.Arbore ab;
        Arbore.Nod nodCurent;
        public HillClimbing(State iState, List<State> fStates, List<iOperator> opr, List<string> log,
              ref Arbore.Arbore Ab)
            : base(iState, fStates, opr, log)
        {
            ab = Ab;
        }
        private List<State> expand(State thisState)
        {
            Nod a = ab.CurrentNod;
           List<State> n = new List<State>();
            for (int i = 0; i <= operatorNumber; i++)
            {
                if (operators[i].available(thisState.CurrentState))
                {
                    var m = (Template)thisState.CurrentState.Clone();
                    State auxiliary = new State(operators.ElementAt(i).execute(m), operators.ElementAt(i));
                    ab.CurrentNod = a;
                    ab.AddS(new Nod(operators.ElementAt(i).ToString() + Environment.NewLine + auxiliary.ToString()));
                    if (!found(auxiliary)) n.Add(auxiliary);
                }
            }
            return n;
        }
        private bool solve(State thisState)
        {

            if (thisState != null)
            {
                if (solutionFound(thisState)) { result = true; return true; }
                List<State> n = expand(thisState);
                State next = null;
                int nextEval = -10;
                for (int i = 0; i < n.Count(); i++)
                {
                    if (eval(n.ElementAt(i)) > nextEval)
                    {
                        next = n.ElementAt(i);
                        nextEval = eval(n.ElementAt(i));
                    }
                }
                if (eval(thisState) > nextEval)
                {
                    result = false;
                    return false;
                }
                else
                {
                    btStack.Push(next);
                    solve(btStack.Peek());
                }
            }
            return false;
        }


        private int eval(State s)
        {
            return function.eval(s, h);
        }
        private bool setSwitcher(bool switcher)
        {
            this.switcher = switcher;
            return switcher;
        }

        public bool isSwitcher()
        {
            return switcher;
        }

        public override bool solveProblem()
        {
            ab.AddS(new Nod(initialState.ToString()));
            solve(initialState);
            if (result == true) return true;
            return false;

        }

        private HillClimbingEvaluate function = new HillClimbingEvaluate();

        public override  void init()
        {
            setSwitcher(false);
        }

        public void setH(iHeuristic h)
        {
            this.h = h;
        }

        public iHeuristic getH()
        {
            return h;
        }	
	

    }
}
